/*********************************************************************

 File: XENON.C (main game file)
 Date: AUG 8, 1996

 File Revision History:

AUG-08-96: smacker buffers 1 and 2 are not cleared any more
	   in closeFirewall() to avoid DOS4GW error on game exit
           under Windows 95
           [Kelly & SMR]/@SMK/

AUG-08-96: system clock is being reset on game exit because
	   keboard / PS2 mouse conflict screws up everything...
	   including the clock -- see reset_clock0() function added
           to KEYBOARD.ASM
           [Kelly & SMR] /@SCL/

AUG-13-96: upon game startup "g_typeofdeath" is assigned a "0" value,
           instead of MAX_DEATHS as was before, to make sure that
           "g_dethframe" gets correct value (see /@DTH2/).
           (DOS4GW bug occurred in "CITY OF LIGHT" /loaded after
           "COASTAL DEFENSES"/ when the game goes to a death scene
           because the program was trying to use wrong frame number
           for begining of the death cut scene (which should have been
           reset upon entering "CITY OF LIGHT").
           [Kelly & SMR] /@DTH/


Game Code Revision History:

Comments:  After heroic struggle with "CRAZY Mouse" bug Chukwuweta came
           up with Version 1.17 dated ...

File changed since then:
     mouse.c
     mouse.h
     keyboard.asm
     xenon.c

*********************************************************************/

#define TESTON 0
#define TESTOF 1
#define TESTLINKS 0
#define _XENON_

#define MT_PS2 0x02 //from mouse.h //@SMR

//#define CHUKWUWETA

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <string.h>
#include <bios.h>
#include <process.h>
#include <stddef.h>
#include <malloc.h>
#include "ail\dll.h"
#include "ail\ail.h"
#include "rad.h"
#include "smack.h"
#include "dosext.h"
#include "svga.h"

#include "sprite.h"
#include "player.h"
#include "radmal.i"
#include "sound.h"
#include "palette.h"
#include "debug.h"
#include "event.h"
#include "sgdef.h"
#include "xenon.h"
#include "menu.h"
#include "keyboard.h"
#include "wdogtimr.h"

// ----------------------------------------------------------------
//    Externs
// ----------------------------------------------------------------
//From the assembly files
extern int bufferpaste(u8 *,u8 *,long,long);
extern int quickrwpanel(u8  *,u8 *,u8 *);
extern int quickcypanel(u8  *,u8 *,u8 *);
extern int quickrwpanel(u8  *,u8 *,u8 *);
extern int pastepanel(u8  *,u8 *,u8 *);
extern int buffer320to352(char *, char *);
extern int buffercopylongs(char *, char *, long);
extern int bufferclear(u8 *,long);
extern int bufferbytepaste(u8 *,u8 *,long,long);
extern int copysmackbuffer(u8 *smackbuffer,u8 *smackbuffer2,u8 numlines);

extern long  g_userbuttons;	 /* State of user input device buttons */
extern long  g_nummenus;
extern char  g_mousetype;
extern long *g_frameevents;
extern unsigned char g_goslow;
extern char g_cutsceneon;
extern void ProcessFrameEvents(long *frameevents);
extern void ProcessSceneEvents(char *scenename);
extern void InitSpecConds();
extern long CheckSpecConds();
extern void updateanimations();
extern TARGET g_targstack[];

extern void reset_clock0();

// ------------------------------------------------------------------
// Main()
//
// Does a lot of initialization, then plays scenes out until done.
// ------------------------------------------------------------------

char *g_stilltextbuffer = (char *) NULL;
long  g_wh;

static	    char *change1="June 13 1996, ver 1.12";
static	    char *change2="June 17 1996, ver 1.13";
static	    char *change3="June 25 1996, ver 1.13";
static	    char *change4="June 27 1996, ver 1.14";
static	    char *change5="July 1 1996,  ver 1.15";
static	    char *change6="July 26 1996, ver 1.16";
static	    char *change7="August 6, 1996. Ver. 1.17";
static	    char *change8="August 8, 1996. Ver. 1.18";


long testHead(void);
void playHead(char *smkfile);
// ----------------------------------------------------------------------

void main(int argc,char * argv[])
{
	char stillbuf[80],message[100],name[50],basename;
	long x,y,pscene,fh,j;
	char *bufferstart;
	// To kill warnings

	argc = argc;
	argv[0] = argv[0];


#ifdef DEBUGGING_ON
	_bios_timeofday(_TIME_GETCLOCK,&startTime);
	openDebug();
#endif

	// Load the configuration file containing sound card info
	loadConfiguaration();

	 //Load the font
#ifdef CHUKWUWETA
	sprintf(g_buffer, "c:\\data\\comp.tff",g_cdrom);
#else
	sprintf(g_buffer, "%s\\data\\comp.tff",g_cdrom);
#endif
	loadfont(g_buffer);

	// Load Game templates
       LoadSavedGamesText();
	// Load Game templates
    // LoadGames();

	initmouse();
   //Set up the keyboard driver
	//FWKeyboard_InstallDriver(g_mousetype);

   //July 25. Fix to PS/2 mouse bug. Pass mouse type to initialization
	FWKeyboard_InstallDriver(g_mousetype);

	// Smacker SVGA setup
	SVGADetect(1);
	SVGASetup(320,200);
	SVGASetGraph();

#ifdef DEBUGGING_ON
	if (argc == 1)
	{
#endif
		sprintf(g_buffer, "%s%s",g_cdrom,g_videotable[VID_LGSLOGO]);
		usePlayer(g_buffer);
		SVGAClear(0); // set the screen to black so we don't get flash!
		sprintf(g_buffer, "%s%s",g_cdrom,g_videotable[VID_VMILOGO]);
		usePlayer(g_buffer);

	g_killscene = FALSE;
		SVGAClear(0); // set the screen to black so we don't get flash!
		sprintf(g_buffer, "%s%s",g_cdrom,g_videotable[VID_FWINTRO1]);
		usePlayer(g_buffer);
		if(g_killscene != TRUE)
		{
		SVGAClear(0); // set the screen to black so we don't get flash!
		sprintf(g_buffer, "%s%s",g_cdrom,g_videotable[VID_FWINTRO2]);
		usePlayer(g_buffer);
		}
	g_killscene = FALSE;

		SVGAClear(0); // set the screen to black so we don't get flash!
		ClearPalette();
	   // Allocate main buffers for Smacker
	   databuf=malloc(60000);
	   smackBuffer=malloc(SCREENBUFFERSIZE);
	   smackBuffer2=malloc(SCREENBUFFERSIZE);
	   memset(smackBuffer,0,SCREENBUFFERSIZE);
	   memset(smackBuffer2,0,SCREENBUFFERSIZE);

	   GetBltMemory(-1);	   //Initialize Blt memory
	   GetTurnMemory(-1);	   //Initialize Turn memory
	   GetMenuMemory(-1);	   //Initialize Menu memory
	   GetSpriteMemory(-1);    //Initialize Sprite memory
	   GetEventMemory(-1);	   //Initialize Event memory
	   GetEventFileMemory(-1); //Initialize Event File memory
	   GetEventFrameMemory(-1);//Initialize Event Frame memory
	   GetSceneMusicMemory(-1);//Initialize Scene Music memory

	   if(!databuf || !smackBuffer || !smackBuffer2)
		fatalerror("Couldn't Malloc Data Buffers");

     start_firewall:
	g_killscene = FALSE;
		g_currentscenenumber=0;
		LoadMenus(GAMEMENUTYPE);
		LoadStl((long) -1,"mainback");
		loadblts();
		buffercopylongs(g_palette,g_stillpalette,(192 *3));
		buffercopylongs((g_palette + (192 *3)),g_panelpalette,(64 *3));
		PaletteSet(g_palette);
		g_pauseon = TRUE;

		ProcessMenu(MAINMENU,g_still);

		if(g_leavegame == TRUE)
		  goto leave_firewall;
	else
		  g_killgame = FALSE;

#ifdef DEBUGGING_ON
	}
	else
	{
	   databuf=malloc(60000);
	   smackBuffer=malloc(SCREENBUFFERSIZE);
	   smackBuffer2=malloc(SCREENBUFFERSIZE);
	   memset(smackBuffer,0,SCREENBUFFERSIZE);
	   memset(smackBuffer2,0,SCREENBUFFERSIZE);
	   if(!databuf || !smackBuffer || !smackBuffer2)
		fatalerror("Couldn't Malloc Data Buffers");
		g_currentscenenumber = atoi(argv[1]);
	    loadblts();
		LoadMenus(GAMEMENUTYPE);
	   // Allocate main buffers for Smacker
		if((g_currentscenenumber < SC_COASTD) || (g_currentscenenumber > SC_FINALC))
			fatalerror("Illegal scene number entered\n");
	}
#endif

	// Load picture data, fonts, etc
	ClearPalette();

	if(g_restoregame != MAX_SAVEDGAMES)
	{
		LoadGame(g_restoregame);
		RestoreGame();
		if(g_currentscenenumber > SC_GRWALL) //Real World menus loaded default
		{
			loadblts();
			LoadMenus(GAMEMENUTYPE);
		}
	}
	else
		inittoolsweaps();

	// Initialialize a bunch of structures
	initplayerinfo();
	initanis();

	//Load the first still screen
	LoadStl(g_currentscenenumber,(char *) NULL);

	// The main loop: Play scenes until g_currentscenenumber is -1
	ClearPalette();

	if(g_restoregame == MAX_SAVEDGAMES)
	 g_player.lives = INITIAL_LIVES;

	while((!g_killgame) && (!g_leavegame))
	{
		//we need this for some dependencies - how many times thru scene...
		g_scenentry[g_currentscenenumber]++;
	  // put up the title still screen.
		PaletteSet(g_stillpalette);
	    g_textcol = g_stilltextcols[g_currentscenenumber];
		g_keypressed = 0;

	   bufferstart=g_still + 100 + (PICWIDTH * 190);
	   bufferbytepaste(bufferstart, g_stilltextbuffer,g_wh,0);
	   sprintf(message,"        LOADING...       ");
	   printx(100,190,message,g_still);
	   SVGABlit(g_still,0,0,320,200,352,0,0);

	   //CSC June27. Fix for 8 meg machines. Do this here to
	   //ensure that enough memory is reserved to open
	   //and play the smack file in playScene.

	sprintf(name,"%s\\data\\%s.smk",g_cdrom,g_scenetable[g_currentscenenumber]);
	sprintf(g_curname,"%s\\data\\%s.smk",g_cdrom,g_scenetable[g_currentscenenumber]);

	if (g_gotsound)
	 {
	  while(1)
	   {
	     if(!(smk=SmackOpen(name,0L,0)))
		  {
		   if(g_soundloadflg)
		    unLoadSomeSound(); //Try and dump some sound, remember to reload it
				       //in case of same scene
	    else break;
	  }
	 else
		  break;
       }

	    if(!smk)
	    {
		  sprintf(message,"Error scene file opening %s\n",name);
		  fatalerror(message);
		 }
	  }
       else if(!(smk=SmackOpen(name,0L, 0)))
	   {
		  sprintf(message,"Error scene file opening %s\n",name);
		  fatalerror(message);
	   }

		if((strlen(g_introtable[g_currentscenenumber])) &&
		   (g_restoregame == MAX_SAVEDGAMES))
		   {
	    sprintf(name,"%s\\data\\%s.smk", g_cdrom,
					   g_introtable[g_currentscenenumber]);

			if(g_gotsound)
			{
		 while(1)
		   {
			if(!(g_smkintro=SmackOpen(name,SMACKTRACKS, SMACKAUTOEXTRA)))
			 {
			  if(g_soundloadflg)
			     unLoadSomeSound(); //Try and dump some sound,
							    //remember to reload it
		    else break;
		 }
		 else
			   break;
		 }

		    if(!g_smkintro)
		     {
			   sprintf(message,"Error scene file opening %s\n",name);
		   fatalerror(message);
			 }
		      }
		  else	if(!(g_smkintro=SmackOpen(name,SMACKTRACKS, SMACKAUTOEXTRA)))
		     {
		       sprintf(message,"Error intro file opening %s\n",name);
		       fatalerror(message);
		     }
		   }

	//process the events for this scene
		InitSpecConds();
		ProcessSceneEvents(g_scenetable[g_currentscenenumber]);

       if(g_gotsound) //Load the sound for the scene
	     LoadSomeSound();

		LoadStl(g_currentscenenumber,(char *) NULL);
		ClearPalette();
		PaletteSet(g_stillpalette);
		g_textcol = g_stilltextcols[g_currentscenenumber];
	    bufferstart=g_still + 100 + (PICWIDTH * 190);
	    bufferbytepaste(bufferstart, g_stilltextbuffer,g_wh,0);
		sprintf(message,"PRESS ANY KEY TO CONTINUE");
	    printx(100,190,message,g_still);
		SVGABlit(g_still,0,0,320,200,352,0,0);
		do
			processuserinput((u8 *)NULL);
		while(!g_keypressed && !g_userbuttons);
		g_textcol=SHOTCOLOR+1;

		// play the opening cut scene if there is one.
		if((strlen(g_introtable[g_currentscenenumber])) &&
		   (g_restoregame == MAX_SAVEDGAMES))
		{
			strcpy(stillbuf,g_introtable[g_currentscenenumber]);
			playIntro(stillbuf);
		}

                // Gameplay starts here!
                // Reset type of death

                g_typeofdeath    = 0;//MAX_DEATHS;//@DTH
		g_powrmult	 =1;

		g_incyberspace = (g_currentscenenumber > SC_GRWALL) ? TRUE : FALSE;
		//Set the game holder
	   if(g_restoregame == MAX_SAVEDGAMES)
		SetGame();


       if(g_gotsound)  // start the music if the user has sound.
	    playSceneMusic();

		playScene(g_scenetable[g_currentscenenumber],
						databuf,
						smackBuffer,
						smackBuffer2);

       if((g_killgame == TRUE) || (g_leavegame == TRUE))
	     break;

		g_blinktxt.numframes = 0; // turn off any flashing text!

		if(g_restoregame == MAX_SAVEDGAMES)
		{
			if(g_currentscenenumber == g_nextscenenumber)
			{
				ResetGame(); //Sorry, didn't make it out bozo
				LoadStl(g_currentscenenumber,(char *) NULL);
			}
			else if(g_nextscenenumber != g_currentscenenumber)
			 {
				unLoadAllSound();
				LoadStl(g_nextscenenumber,(char *) NULL);
			 }

			if((((g_nextscenenumber > SC_GRWALL) &&
				  (g_currentscenenumber < SC_PORTAL)) ||
			     ((g_nextscenenumber < SC_PORTAL) &&
				  (g_currentscenenumber > SC_GRWALL))) ||
				  (g_currentscenenumber == SC_PORTAL))
			{
				g_currentscenenumber = g_nextscenenumber;
				initplayerinfo();
				inittoolsweaps(); /*Cyber Change*/
				loadblts();
				LoadMenus(GAMEMENUTYPE);
			 }

			g_currentscenenumber = g_nextscenenumber;
			g_killscene = FALSE;
		}
		else
		{
			pscene = g_currentscenenumber;
		LoadGame(g_restoregame);
			RestoreGame();
			if(((pscene > SC_GRWALL) && (g_currentscenenumber < SC_PORTAL)) ||
		      ((pscene < SC_PORTAL) && (g_currentscenenumber > SC_GRWALL)))
			{
//				free(g_panelpalette);
//				g_panelpalette = NULL;
				LoadMenus(GAMEMENUTYPE);
				loadblts();
				initplayerinfo();
			}
			g_killscene = FALSE;
			if(pscene != g_currentscenenumber)
			 {
			  LoadStl(g_currentscenenumber,(char *) NULL);
			  unLoadAllSound();
			 }
		}
	}

    unLoadAllSound();
	if(g_leavegame != TRUE)
	   goto start_firewall;


 leave_firewall:
    sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_CREDITS]);
    usePlayer(g_buffer);

	FWKeyboard_DestallDriver(); //Remove the keyboard driver
	SVGASetText();	// Back to text mode

#ifdef DEBUGGING_ON
	printf("Frames/Sec = %d\n",(frames*182) / ((endTime - startTime)*10));
#endif

	closeFirewall();
        printf("Thank you for playing Firewall!\n");

        //if (g_mousetype == MT_PS2) {
	   reset_clock0();
        //   printf("[1996.V.1.18-PS2M]\n");
        //} else printf("[1996.V.1.18-SRLM]\n");
}

// ----------------------------------------------------------------------
// playScene()
//
// Play out a scene.  Load the appropriate tables and sounds, open the
// smacker file, and loop through each frame, handling events and pasting
// sprites as necessary.
// ----------------------------------------------------------------------

playScene(char *basename,u8 *databuf,u8 *smackBuffer,u8 *smackBuffer2)
{
	u32 i, x;
	u32 bytecount;
	static char name[50],message[100];
	char errormsg[32],*smkpnt;
	long jumptoframe;
	static long panelwh=0;
	long g_lasthitpoints;
	char resetpalette= TRUE,lastgamepalette;
	PENTRY *pentry;

	//Restore the panel palette
	if(!panelwh)
	{
		panelwh = 192 << 16;
		panelwh++;
	}

	g_curscene  = g_nextscenenumber = g_currentscenenumber;
	g_killgame  = FALSE;
	g_killscene = FALSE;

	// Make sure buffers are aligned on a DWORD (4-byte) boundary
	// so that blitting functions work faster.
	smackBuffer =alignTo4(smackBuffer);
	smackBuffer2=alignTo4(smackBuffer2);

	// Load turn data (if any)
	sprintf(name,"%s\\data\\%s.trn",g_cdrom,basename);
	g_turndataready = LoadTurnData(name);

	//Init branching
    g_branchframe = -1;

	//Init Player
	g_branchwarn	   = 0;
	g_playerdead	   = FALSE;
    if(g_restoregame == MAX_SAVEDGAMES)
	  g_player.hitpoints = INITIAL_LIFE;

    SVGAClear(0);
    buffercopylongs(g_palette +(192 *3),g_panelpalette,(64 * 3));
    PaletteSet(g_palette);


    //CSC June 27 1996 Smack file sound have already been opened in main

	if (smk)
	{
		// Make sure smacker data goes to a buffer, not the screen
		if(g_restoregame == MAX_SAVEDGAMES)
			i = 1;
		else
	   {
			//The palette and smackBuffer2 should have been set by
			//restoregame
			SVGAClear(0);
			PaletteSet(g_palette);
			buffercopylongs(g_palette, g_savedgame.palette, PALSIZE);
			SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
			SmackGoto(smk,(g_restoreframe+1));
			while (SmackWait(smk));
			i=(g_restoreframe +1);
	   }

#ifdef DEBUGGING_ON
write_trace("back from smackopen.\n\n");
#endif
		if(g_restoregame == MAX_SAVEDGAMES)
			SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);

		g_gameplaying  = TRUE;
		g_restoreframe =  0;
		g_restoregame  = MAX_SAVEDGAMES;
		// Loop through all frames (not strictly necessary...a
		// while(g_curscene==g_currentscenenumber) might be more appropriate.)

		FWWdogtimer_InstallDriver();
		for(; i<=smk->Frames;i++)
		{
            g_wdogtimersec = 0;
			g_curframe = i-1;

			// Decode the current frame into the buffer.
			SmackDoFrame(smk);

			// Copy the decoded picture to a buffer where we will do all
			// our work.  Do not write into the original buffer or it will
			// mess up all the delta information that smacker uses.
//			copysmackBuffer(smackBuffer,smackBuffer2);
#if TESTOF
			if(g_frameevents[g_curframe]) // Events on this frame
				ProcessFrameEvents((long *) g_frameevents[g_curframe]);
#endif

			if (!g_cutsceneon)
				copysmackBuffer((smackBuffer+SAFEAREA),
							(smackBuffer2+g_windowx+(PICWIDTH * g_windowy)),160);
			g_savewindowx = g_windowx;
			g_savewindowy = g_windowy;

			// Retrieve the sprite data for the frame that has been mixed
			// into the smacker file by SMIX.
			bytecount=SmackGetTrackData(smk,databuf,SMACKTRACK1);
			processSprites(databuf,(smackBuffer+SAFEAREA));

			// Do all the work of pasting stuff onto the background.
			// Ordering becomes important here...

//	    testcollisionmap(smackBuffer);
//#if TESTOF
//			if(g_frameevents[g_curframe]) // Events on this frame
//				ProcessFrameEvents((long *) g_frameevents[g_curframe]);
#//endif

			//Have we recieved the order to die?
			if((g_killscene == TRUE) ||
			   (g_killgame == TRUE)  ||
			   (g_leavegame == TRUE))
				goto done;

			if ((g_cutsceneon == FALSE) &&
				 (g_killgame  == FALSE)  &&
				 (g_leavegame  == FALSE)  &&
				 (g_killscene == FALSE)  &&
				 (g_playerdead==FALSE))
			{  //We're not in a cut scene
				//and we're not exiting or dead
				if(resetpalette == FALSE)
				 lastgamepalette = smk->CurPalette;

				// Check user input, mouse, keys
				g_lasthitpoints = g_player.hitpoints;
				processuserinput(smackBuffer+SAFEAREA);

#if TESTOF
					// Paste in enemy sprites and check for shots
				SpritePlaceOnScreen(smackBuffer+SAFEAREA);

				if(g_player.hitpoints < g_lasthitpoints)
					startPaletteFlash(100,0,0,2);
#endif


#if TESTOF
				// Deal with the player's shots
				playershot(smackBuffer+SAFEAREA);
				// Deal with animations (explosions,etc)
				drawplayersprite(smackBuffer+SAFEAREA);// Draw the player's ship
				updatePanel(smackBuffer+SAFEAREA);// Copy the panel in
				updateanimations(smackBuffer+SAFEAREA);

#endif
				// Blit the finished frame onto the screen

				if(resetpalette == TRUE)
				{
					SVGAClear(0);
					PaletteSet(g_palette);
					smkpnt = (char *) smk + 0x6BC;
					*smkpnt = g_curframe;
					resetpalette = FALSE;
					if((g_branchframe != -1) &&
					   (g_currentscenenumber == SC_DATACL)) goto check_branches;
				}
			}
			else
			 {
			   resetpalette = TRUE;
			   processkeyboard();
			 }

			if (smk->NewPalette)// || g_firstcut)
			{
				SVGAClear(0);
				if(g_cutsceneon)
				{
					resetpalette = TRUE;
					PaletteSet((smk->CurPalette==1)?smk->Col1:smk->Col2);
				}
				else
				{
					buffercopylongs(g_palette,
								    (smk->CurPalette==1)?smk->Col1:smk->Col2,
									(192 * 3));
					PaletteSet(g_palette);
				}
			}

			//Have we recieved the order to die?
			if((g_killscene == TRUE) ||
			    (g_leavegame == TRUE) ||
			    (g_killgame == TRUE))
				goto done;

			// Blit the finished frame onto the screen
			if(g_cutsceneon)
				SVGABlit(smackBuffer2,0,0,320,200,352,0,0);
			else
				SVGABlit((smackBuffer+SAFEAREA),0,0,320,200,352,0,0);

			updatePaletteFlash();

    if ((g_currentscenenumber == SC_PDEFEN) && (g_curframe == 206))
    {
	  g_killscene=TRUE;
	  g_player.lives--;
      g_dethframe = g_deaths[PD_DEATH_BY_GENERALSHOT];
      SmackGoto(smk,(g_dethframe +1));
      i=g_dethframe;
      while (SmackWait(smk))
	   {
        if(g_wdogtimertrg)
		 {
			SmackClose(smk);
	        smk=SmackOpen(g_curname,0L,0);
			SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
			SmackGoto(smk,(g_dethframe+1));
			g_wdogtimertrg = 0;
		 }
	   }
	  continue;
    }

	if (g_currentscenenumber == SC_DATACL && g_curframe == g_pongframe)
	{
		if(testHead())
		 {
		   g_gameplaying=FALSE;
		   sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_PONG]);
		   g_pongframe = -1;
		   resetpalette = TRUE;
		   if(g_gotsound)
		   {
			 AIL_end_sample(smp[SMUSIC]);
			 if (AIL_sample_status(smp[CLUE]) != SMP_DONE)
				AIL_end_sample(smp[CLUE]);
		   }

		  SVGAClear(0);
		  FWWdogtimer_DestallDriver(); //Turn off the watch dog timer.
		  							   //So it doesn't get screwed up
									   //by play head.
		  playHead(g_buffer);
		  FWWdogtimer_InstallDriver(); //Turn that baby back on
#if 1
//CSC June 13 1996, fix to head video after dogy death in DC
//Stops exit from and restart of, scene
		  g_killscene=FALSE;
#endif
		  if(g_gotsound)
			playSceneMusic();

#if 1
//CSC June 13 1996, fix to head video after dogy death in DC
//Stops palette flash
	    SVGAClear(0);
#endif
		 }

		if (smk)
		{
			PaletteSet(g_palette);
			SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
			SmackGoto(smk, g_curframe+1);
			g_gameplaying=TRUE;
#if 1
//CSC June 13 1996, fix to head video after dogy death in DC
	    continue; //Loop back and continue playing old scene
#endif
		}
	}

			// Advance smacker to the next frame
			if ((i!=smk->Frames) && (g_branchframe == -1))
			{
				SmackNextFrame(smk);
				while (SmackWait(smk))
                 if(g_wdogtimertrg)
		         {
					SmackClose(smk);
	        		smk=SmackOpen(g_curname,0L,0);
					SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
					SmackGoto(smk,(i+1));
					g_wdogtimertrg = 0;
				}
			}

			//Are you dead?
                        if ((g_player.hitpoints <= 0) && (!g_playerdead))
			{
				g_playerdead = TRUE;
				g_killscene  = TRUE;
				g_player.lives--;
				x = random(5);
				if (g_player.lives == x)
					g_videotoplay = VID_CHICKENS; // play the 'chickens' video randomly

                                //@DTH2
                                if(g_typeofdeath < MAX_DEATHS)
					g_dethframe = g_deaths[g_typeofdeath];

                                //The following fixes DOS4GW bug that occurs
                                //in CITY OF LIGHT
                                //if (g_currentscenenumber == SC_CITYLT)
                                //g_dethframe = 1112;

                                if(g_dethframe > -1)
				{
                                        SmackGoto(smk,(g_dethframe +1));

					i=g_dethframe;
					while (SmackWait(smk))
					 {
        				if(g_wdogtimertrg)
		 					{
								SmackClose(smk);
	       						smk=SmackOpen(g_curname,0L,0);
								SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
								SmackGoto(smk,(g_dethframe+1));
								g_wdogtimertrg = 0;
		 					}
					 }
				}

				continue; //Jump back to top of loop so
					  //Frame events for the death frame are processed
			}

			// Have we recieved a signal to go quit?
			if((g_killscene == TRUE) ||
			   (g_leavegame == TRUE) ||
			   (g_killgame == TRUE))
				goto done;

			// How about those good old special conditions ?
			if(((jumptoframe = CheckSpecConds()) != g_curframe) &&
				 (jumptoframe > 0))
			{
				SmackGoto(smk,(jumptoframe +1));
				i=jumptoframe;
				while (SmackWait(smk))
				 {
        			if(g_wdogtimertrg)
					 {
						SmackClose(smk);
	        			smk=SmackOpen(g_curname,0L,0);
						SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
						SmackGoto(smk,(jumptoframe+1));
						g_wdogtimertrg = 0;
		 			}
				 }
			}

			// Well then how about those old branches?
			// or jumps
check_branches:
			if(g_branchframe != -1) //This would have been set by
			{
				SmackGoto(smk,(g_branchframe +1));
				i=g_branchframe;
				g_branchframe = -1;
				while (SmackWait(smk))
				 {
        			if(g_wdogtimertrg)
					 {
						SmackClose(smk);
	        			smk=SmackOpen(g_curname,0L,0);
						SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
						SmackGoto(smk,(g_branchframe+1));
						g_wdogtimertrg = 0;
		 			}
				 }
			}

			if(g_goslow)
				g_pauseon=~(FALSE);

//	  while(g_pauseon) //Old way of pausing using Z for step by step
//	    processkeyboard();
		if(g_pauseon != FALSE) /*Wait for end of pause*/
			{ 
			  g_wdogtimeroff = 1; g_wdogtimersec = 0;
			  ProcessMenu(MAINMENU,(smackBuffer+SAFEAREA));
			  g_wdogtimeroff = 0; 
			}

			if((g_killscene == TRUE) ||
			   (g_killgame == TRUE)  ||
			   (g_leavegame == TRUE))
				goto done;

//#if TESTOF
#if 1
			if((g_currentscenenumber == SC_DATACL) && (g_curframe == 1321))
			{
				SVGAClear(0); // set the screen to black so we don't get flash!
				LoadStl((long) -1,"secrback");
				PaletteSet(g_stillpalette);
				LoadMenus(SCRMMENUTYPE);
				g_windowx = g_windowy = 0;
			    g_wdogtimeroff = 1; g_wdogtimersec = 0;
				ProcessMenu(SCRMMENU,g_still);
			    g_wdogtimeroff = 0; 
				SVGAClear(0); // set the screen to black so we don't get flash!
				PaletteSet(g_palette); //Reset the Palette
				LoadMenus(GAMEMENUTYPE);
				if(g_secrroomsolved == FALSE)
				{
				    g_player.lives--;
					g_dethframe = g_deaths[DC_DEATH_BY_SRDAEMON];
					if(g_dethframe > -1)
					{
						SmackGoto(smk,(g_dethframe +1));
						i=g_dethframe;
						while (SmackWait(smk))
						 {
        					if(g_wdogtimertrg)
								{
									SmackClose(smk);
	   							    smk=SmackOpen(g_curname,0L,0);
									SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
									SmackGoto(smk,(g_dethframe+1));
									g_wdogtimertrg = 0;
		 						}
						 }
					}
				    continue; //Jump back to top of loop so
						 //Frame events for the death frame are processed
				}
				else
				{
				    SmackGoto(smk,1197);
					i = 1196;
					while (SmackWait(smk))
					{
				        if(g_wdogtimertrg)
		 					{
							 SmackClose(smk);
	       					 smk=SmackOpen(g_curname,0L,0);
							 SmackToBuffer(smk,0,0,352,200,smackBuffer2,0);
							 SmackGoto(smk,1197);
							 g_wdogtimertrg = 0;
		  					}
		 			}

					sprintf(g_blinktxt.blinktext, "AIRES MODULE AQUIRED");
					g_blinktxt.numframes = NUMBLINKFRAMES;
					g_weaps[WP_AiresMod].weapaquired    = TRUE;
					if((g_weaps[WP_AiresCom].weapaquired == TRUE) &&
						(g_weaps[WP_AiresMod].weapaquired == TRUE))
					{
						g_weaps[WP_AiresCom].weapaquired = FALSE;
						g_weaps[WP_AiresMod].weapaquired = FALSE;
						g_weaps[WP_AIRES].weapaquired	 = TRUE;
						if((g_selectedweap == WP_AiresCom) ||
						(g_selectedweap == WP_AiresMod))
							g_selectedweap = WP_AIRES;
					}
				}
			   LoadStl(g_currentscenenumber,(char *) NULL);
			}

#endif
			if(g_curframe == (smk->Frames-1))
			{
#if TESTON
				fclose(g_testfile);
#endif
				g_leavegame=TRUE;
				goto done;
			}
		}

		done:
		FWWdogtimer_DestallDriver();
		g_gameplaying = FALSE;
		g_endcut =-1;
		fadeWholePalToBlack(NORMALPALFADELENGTH/4);
		bufferclear(smackBuffer,SCREENBUFFERSIZE);
		SVGABlit(smackBuffer, 0, 0, 320, 200, 352, 0, 0);
		SmackClose(smk);
		for (i=0; i< MAX_DEATHS; i++)
			g_deaths[i]=-1;
		g_numdeaths=-1;
		g_SpritesOnScreen = (TARGET *) NULL;
		if(g_gotsound)
		{
			AIL_end_sample(smp[SMUSIC]);
			if (AIL_sample_status(smp[CLUE]) != SMP_DONE)
				AIL_end_sample(smp[CLUE]);
		}
		// there is some ordering importance here - I think that we always
		// play a cutscene BEFORE a video if we have them lined up that way. -MCR
		if((g_cutplay == -1)&& (g_dethframe != -1) &&
		   (g_frameevents[g_dethframe]) &&
		   (g_playerdead || g_player.hitpoints ==0))
		  ProcessFrameEvents((long *) g_frameevents[g_dethframe]);

		if (g_cutplay != -1)
		{
			sprintf(g_buffer,"%s%s",g_cdrom,g_cutscenes[g_cutplay]);
			sprintf(g_cutname,"%s%s",g_cdrom,g_cutscenes[g_cutplay]);

			if (g_gotsound)
			 {
			   if(!(smkcut = SmackOpen(g_buffer,SMACKTRACKS,SMACKAUTOEXTRA)))
			 {
			  sprintf(message,"Error opening %s\n",g_buffer);
			  fatalerror(message);
			 }
			 }
			else
			 {
			  if(!(smkcut = SmackOpen(g_buffer,0L,SMACKAUTOEXTRA)))
		       {
			    sprintf(message,"Error opening %s\n",g_buffer);
			    fatalerror(message);
		       }
			 }

			if (smkcut)
			{
				playCut(smkcut);
				SVGAClear(0); // set the screen to black so we don't get flash!
					SmackClose(smkcut);
				}
				smkcut=NULL;
				g_cutplay = -1;
			}


			if (g_player.lives <= 0)
			{
				g_killgame = TRUE;
				g_videotoplay = VID_NEGEND;
			}

			if (g_videotoplay !=-1)
			{
				if ((g_currentscenenumber == SC_FIREWL) && (g_player.lives <= 0))
				{
					g_videotoplay = VID_PITIFUL;
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[g_videotoplay]);
					usePlayer(g_buffer);
					g_videotoplay = VID_NEGEND;
				}
				if (g_videotoplay == VID_BLOODHEAD)  // bloody head - put up poem!
				{
				    unLoadAllSound();
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_BLOODHEAD]);
					usePlayer(g_buffer);
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_POEMS]);
					usePlayer(g_buffer);
					g_videotoplay =-1;
					SVGAClear(0); // set the screen to black so we don't get flash!
					return;
				}

				if (g_videotoplay == VID_POSEND)
				 {
				    unLoadAllSound();
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_POSEND]);
					usePlayer(g_buffer);
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_WINOVER]);
					usePlayer(g_buffer);

					g_killgame=TRUE;
					g_leavegame = FALSE;
					g_currentscenenumber=0;
					initplayerinfo();
					g_videotoplay =-1;
					SVGAClear(0); // set the screen to black so we don't get flash!
					return;
				 }
				else if (g_videotoplay == VID_NEGEND)
				{
				    unLoadAllSound();
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_NEGEND]);
					usePlayer(g_buffer);
					sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[VID_LOSEOVER]);
					usePlayer(g_buffer);

					g_killgame=TRUE;
					g_leavegame = FALSE;
				g_currentscenenumber=0;
				initplayerinfo();
				g_videotoplay =-1;
				SVGAClear(0); // set the screen to black so we don't get flash!
				return;
			}
			else
			{
			if(g_currentscenenumber != g_nextscenenumber)
			 unLoadAllSound();

			sprintf(g_buffer,"%s%s",g_cdrom,g_videotable[g_videotoplay]);
			usePlayer(g_buffer);
			}

			g_videotoplay=-1;
			SVGAClear(0); // set the screen to black so we don't get flash!
		}
	}
}

// ----------------------------------------------------------------------
// playIntro()
//
// Play out an opening scene - these are kept in separate smacker files.
// ----------------------------------------------------------------------

playIntro(char *basename)
{
	u32 i;
	char name[80];
	char message[100];

	// Make sure buffers are aligned on a DWORD (4-byte) boundary
	// so that blitting functions work faster.
	smackBuffer2=alignTo4(smackBuffer2);

#if 0
	// Open the Smacker file and start playing it.
	sprintf(name,"%s\\data\\%s.smk",g_cdrom,basename);
	if (g_gotsound)
		smk=SmackOpen(name,SMACKTRACKS, SMACKAUTOEXTRA);
	else
		smk=SmackOpen(name,0L, SMACKAUTOEXTRA);
#endif

 //CSC June 26 1996, If there's sound, the file should already be opened
 //		     in main.

	if (!g_gotsound)
	 {
	    sprintf(name,"%s\\data\\%s.smk",g_cdrom,basename);
		if(!(g_smkintro=SmackOpen(name,0L, SMACKAUTOEXTRA)))
		 {
		   sprintf(message,"Error opening %s\n",g_buffer);
		   fatalerror(message);
		 }
	 }

	if (g_smkintro)
	{
		// Make sure smacker data goes to a buffer, not the screen
		SmackToBuffer(g_smkintro,0,0,352,200,smackBuffer2,0);
		g_killscene = FALSE;

		// Loop through all frames (not strictly necessary...a
		// while(g_curscene==g_newscene) might be more appropriate.)
		FWWdogtimer_InstallDriver();
		for(i=1;i<=g_smkintro->Frames;i++)
		{
#ifdef DEBUGGING_ON
			frames++;
#endif
            g_wdogtimersec = 0;
			// Decode the current frame into the buffer.
			SmackDoFrame(g_smkintro);

			// If there is a new palette in the smacker file, set it.
			// This may not work well for multi-palette files.
			if (g_smkintro->NewPalette)
			{
				SVGAClear(0);// set the screen to black so we don't get flash!
				setPal((g_smkintro->CurPalette==1)?g_smkintro->Col1:g_smkintro->Col2,0,256);
			}
			SVGABlit(smackBuffer2, 0, 0, 320, 200, 352, 0, 0);
			SmackNextFrame(g_smkintro);

			while(SmackWait(g_smkintro))
			 {
	         processkeyboard();
			 if (g_killscene==TRUE)
			  {
			    g_killscene = FALSE;
			    goto introdone;
			  }

				if(g_wdogtimertrg)
		 		 {
				   SmackClose(g_smkintro);
//	           g_smkintro=SmackOpen(name,0L, SMACKAUTOEXTRA);
#if 1 
	               if (g_gotsound)
	 	             g_smkintro=SmackOpen(name,SMACKTRACKS, SMACKAUTOEXTRA);
					else
					g_smkintro=SmackOpen(name,0L, SMACKAUTOEXTRA);
#endif
		           SmackToBuffer(g_smkintro,0,0,352,200,smackBuffer2,0);
				   SmackGoto(g_smkintro,(i+1));
				   g_wdogtimertrg = 0;
		  		}
			 }
		}

introdone:
		FWWdogtimer_DestallDriver();
		SmackClose(g_smkintro);
		fadeWholePalToBlack(NORMALPALFADELENGTH/4);
	}
}

// ----------------------------------------------------------------------
// playCut()
//
// Play a cut scene - these are kept in separate smacker files.
// ----------------------------------------------------------------------

playCut(Smack *smkcut)
{
	long i;
	char g_savegameplaying;
	// Make sure buffers are aligned on a DWORD (4-byte) boundary
	// so that blitting functions work faster.
	smackBuffer2=alignTo4(smackBuffer2);

	if (smkcut)
	{
		// Make sure smacker data goes to a buffer, not the screen
		g_killscene = FALSE;
		SmackToBuffer(smkcut,0,0,352,200,smackBuffer2,0);

		// Loop through all frames
		g_savegameplaying = g_gameplaying;
		g_gameplaying = FALSE;

		FWWdogtimer_InstallDriver();
		for(i=1;i<=smkcut->Frames;i++)
		{
			// Decode the current frame into the buffer.
            g_wdogtimersec = 0;
			SmackDoFrame(smkcut);

			// If there is a new palette in the smacker file, set it.
			if (smkcut->NewPalette)
			{
				SVGAClear(0);// set the screen to black so we don't get flash!
				setPal((smkcut->CurPalette==1)?smkcut->Col1:smkcut->Col2,0,256);
			}

			SVGABlit(smackBuffer2, 0, 0, 320, 200, 352, 0, 0);
			SmackNextFrame(smkcut);
			while(SmackWait(smkcut))
			 {
				processkeyboard();
				if (g_killscene==TRUE)
				{
					g_killscene=FALSE;
					goto cutdone;
				}
				if(g_wdogtimertrg)
		 		 {
				   SmackClose(smkcut);
			       smkcut = SmackOpen(g_cutname,0L,SMACKAUTOEXTRA);
		           SmackToBuffer(smkcut,0,0,352,200,smackBuffer2,0);
				   SmackGoto(smkcut,(i+1));
				   g_wdogtimertrg = 0;
		  		}
			 }
		}
cutdone:
		FWWdogtimer_DestallDriver();
		fadeWholePalToBlack(NORMALPALFADELENGTH/2);
	}

   g_gameplaying = g_savegameplaying;
}
// ----------------------------------------------------------------------
// usePlayer()
// Tiny Smacker player that still does everything
// ----------------------------------------------------------------------

void usePlayer(char *smkfile)
 {
   Smack* smk1=NULL;
   u32 i;
   char message[100];
   long soundwasloaded;
   long fh;

#if 0
	if (g_gotsound)
	 {
	   if(!(smk1=SmackOpen(smkfile,SMACKTRACKS,SMACKAUTOEXTRA)))
	    {
	      sprintf(message,"Error opening %s\n",smkfile);
	      fatalerror(message);
	    }
	 }
#endif

	if (g_gotsound)
	 {
	  soundwasloaded = g_soundloadflg;
	  while(1)
	   {
	     if(!(smk1=SmackOpen(smkfile,SMACKTRACKS,SMACKAUTOEXTRA)))
		  {
		   if(g_soundloadflg)
		    unLoadSomeSound(); //Try and dump some sound, remember to reload it
				     //in case of same scene
	    else break;
	  }
	 else
		  break;
       }

	   if(!smk1)
	    {
	      sprintf(message,"Error opening %s\n",smkfile);
	      fatalerror(message);
	    }
	 }
	else
	 {
	   if(!(smk1=SmackOpen(smkfile,0L,SMACKAUTOEXTRA)))
	    {
	      sprintf(message,"Error opening %s\n",smkfile);
	      fatalerror(message);
	    }
     }

	if (smk1)
		{
		    FWWdogtimer_InstallDriver();
			g_killscene=FALSE;
			SVGADetect(1);
			if (SVGASetup(smk1->Width,smk1->Height))
			{

				SmackToScreen(smk1,0,0,
								SVGABytesPS(),
								SVGAWinTbl(),
								SVGASetBank());

				SVGASetGraph();
				for(i=1;i<=smk1->Frames;i++)
				{
                    g_wdogtimersec = 0;
					if (smk1->NewPalette)
						PaletteSet((smk1->CurPalette==1)?smk1->Col1:smk1->Col2);
					SmackDoFrame(smk1);
					if (i!=smk1->Frames)
						SmackNextFrame(smk1);
					else goto videodone;

					while (SmackWait(smk1))
			 		{
						processkeyboard();
						if (g_killscene==TRUE)
							goto videodone;
					if(g_wdogtimertrg)
		 				{
						 SmackClose(smk1);

						 if(g_gotsound)
	                       smk1=SmackOpen(smkfile,SMACKTRACKS,SMACKAUTOEXTRA);
						 else
	                       smk1=SmackOpen(smkfile,0,SMACKAUTOEXTRA);

				 		 SmackGoto(smk1,(i+1));
				         SmackToScreen(smk1,0,0,
						 				SVGABytesPS(),
										SVGAWinTbl(),
										SVGASetBank());
						 g_wdogtimertrg = 0;
		  				}
			       }
				}
			}

	videodone:
		    FWWdogtimer_DestallDriver();
			SmackClose(smk1);
		}

//CSC June 27 1996 Do this in main so that we don't get
//black screen pause while sound loads
#if 0
//Reload the sound that was dumped to make this smackfile play
  if((g_gotsound) &&
     (soundwasloaded) &&
	 (g_currentscenenumber == g_nextscenenumber))
      LoadSomeSound();
#endif
}

//Test to make sure we can open and play the head animation
long testHead()
 {
   void *tmem[20];
   long x=0,y;

   if((tmem[x++] = (void *) malloc(1936)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(4096)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(1394)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(397960)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(103980))) {free(tmem[--x]);}
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(16548)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
		  }

   if((tmem[x++] = (void *) malloc(664))) {free(tmem[--x]);}
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(664)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(8192)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(28672)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(16384)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(664))) free(tmem[--x]);
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(664))) free(tmem[--x]);
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(664))) free(tmem[--x]);
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(664))) free(tmem[--x]);
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(664))) free(tmem[--x]);
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }

   if((tmem[x++] = (void *) malloc(1024)));
    else {
	       x-=2;
	       for(y=x; y >= 0; --y) free(tmem[y]);
		   return(0);
	     }


   --x;
   for(y=x; y >=0; --y)
     free(tmem[y]);

   return(1);
 }

void playHead(char *smkfile)
 {
   Smack* smk1=NULL;
   u32 i;
   char message[100];
   long soundwasloaded;
   long fh;

	if (g_gotsound)
	 {
	     if(!(smk1=SmackOpen(smkfile,SMACKTRACKS,SMACKAUTOEXTRA)))
		   return;
     }
	else
	 {
	   if(!(smk1=SmackOpen(smkfile,0L,SMACKAUTOEXTRA)))
	     return;
     }

	g_killscene=FALSE;

	SVGAClear(0);
	SVGADetect(1);
	if (SVGASetup(smk1->Width,smk1->Height))
	{
	SmackToScreen(smk1,0,0,SVGABytesPS(),SVGAWinTbl(),SVGASetBank());
				SVGASetGraph();

	  FWWdogtimer_InstallDriver();
	  for(i=1;i<=smk1->Frames;i++)
	   {
            g_wdogtimersec = 0;

		if (smk1->NewPalette)
		  PaletteSet((smk1->CurPalette==1)?smk1->Col1:smk1->Col2);

	    SmackDoFrame(smk1);
		if (i!=smk1->Frames)
			SmackNextFrame(smk1);

				while (SmackWait(smk1))
				{
				processkeyboard();
				if (g_killscene==TRUE)
					goto videodone1;
				 if(g_wdogtimertrg)
		 		   {
					SmackClose(smk1);
	                if (g_gotsound)
	                 {
	                  if(!(smk1=SmackOpen(smkfile,SMACKTRACKS,SMACKAUTOEXTRA)))
	                     goto videodone1;
                     }
 	                else
	                 {
	                   if(!(smk1=SmackOpen(smkfile,0L,SMACKAUTOEXTRA)))
	                     goto videodone1;
                     }

					SmackGoto(smk1,(i+1));
	                SmackToScreen(smk1,0,0,SVGABytesPS(),SVGAWinTbl(),SVGASetBank());
					g_wdogtimertrg = 0;
		  		  }
				 }
		}
	}

videodone1:
	  FWWdogtimer_DestallDriver();
   SmackClose(smk1);
   SVGAClear(0);
}

	// ----------------------------------------------------------------------
	// ----------------------------------------------------------------------
	//   processSprites()
	//
	// Interpret the sprite data we read out of the data stream.
	// -----------------------------------------------------------------------

	processSprites(u8 *databuf,u8 *smackerbuf)
	{
		long i;
		static long ctarcount=0;
	// The first short is a bitmask of what channels have data for them
		short chanmask=*((short *)databuf)++;
	//  short x,y;
		spriteptr spr;
		long coldata=chanmask&0x8000;
		static long g_testchannels[NUMSPRITECHANNELS];

	#if TESTON
		if(g_testfile == (FILE *) NULL)
		{
			g_testfile = fopen("test.chn","wt");
			for(i=1;i<NUMSPRITECHANNELS;i++)
				g_testchannels[i] = -1;
		}
	#endif

		//To Kill Warning
		smackerbuf = smackerbuf;

		for(i=1;i<15;i++)   // Note that channel 0 is considered the background.
		{
			if(chanmask&1) // If the bit is set, fill in the g_pastein structure
			{
	#if TESTON
				if(g_testchannels[i] == -1)
					g_testchannels[i] = g_curframe;
	#endif
				g_pastein[i].x=*((short *)databuf)++;
				g_pastein[i].y=*((short *)databuf)++;
				g_pastein[i].spritedata=spr=((spriteptr)databuf)++;
				spr->data=databuf;
				databuf+=spr->datasize;
			}
		   else // Otherwise, mark in unused.
			{
				g_pastein[i].spritedata=NULL;
	#if TESTON
				if(g_testchannels[i] != -1)
				{
					fprintf(g_testfile,"%d  ctar    %d      %d  unkn  %d\n",
									g_testchannels[i],
									(g_curframe-1),
									i,ctarcount++);

					g_testchannels[i] = -1;
				}
	#endif
			}
			chanmask=chanmask>>1;	// Shift to next bit in mask
		}
		if(coldata) // Test for presence of background collision map
			g_collisionmap=databuf;
		else
			g_collisionmap=NULL;
	}

	// ---------------------------------------------------------------------
	//   alignTo4()
	//
	// Align a pointer to a DWORD (4-byte) boundary.
	// ---------------------------------------------------------------------

	u8 *alignTo4(u8 *ptr)
	{
		u32 addr=(long)ptr;
		switch(addr&3)	    // This is pretty clumsy, actually. :)
		{
			case 3: return(ptr+1);
			case 2: return(ptr+2);
			case 1: return(ptr+3);
			case 0: return(ptr);
		}
		return NULL;
	}

	// ----------------------------------------------------------------------
	//    pastToBuffer()
	//
	// For pasting a variable size picture into a 352x200 buffer.
	//
	// ----------------------------------------------------------------------

	void pastToBuffer(u8 *to,u8 *from,long width,long height)
	{
		long row,col;
		for(row=0;row<height;row++)
		{
			for(col=0;col<width;col++)
				*to++=*from++;
			to+=352-width;
		}
	}

	// ------------------------------------------------------------------------
	//   updatePanel()
	//
	// Copy the control panel into the working buffer.  Write in the names
	// of the currently selected weapons and tools, the current damage level,
	// and any other control info.	Also takes care of the hud-message.  This
	// can be a good place to put debugging information.
	// ------------------------------------------------------------------------

	updatePanel(u8 *smackBuffer)
	{
		u8 *helthstart,*livesstart;
		u8 *bufstart=(smackBuffer);

		long helth_x,helth_y,weap_x,weap_y,hw,offset;
		long helth_width  = (g_incyberspace) ? CYBHELTH_WIDTH  : RWDHELTH_WIDTH;
		long helth_height = (g_incyberspace) ? CYBHELTH_HEIGHT : RWDHELTH_HEIGHT;

		long lives_x,lives_y,lives_init,lives_post,lives_inc;
		long lives_width  = (g_incyberspace) ? CYBLIVES_WIDTH  : RWDLIVES_WIDTH;
		long lives_height = (g_incyberspace) ? CYBLIVES_HEIGHT : RWDLIVES_HEIGHT;
		char message[64];

		if (g_flash.timer)
			pastepanel(bufstart,g_panel.data,g_panel.map);
		else if (g_incyberspace)
			quickcypanel(bufstart,g_panel.data,g_panel.map);
		else
			quickrwpanel(bufstart,g_panel.data,g_panel.map);

		if(g_player.hitpoints > 0)
		{
			lives_inc  = (g_incyberspace) ? CYBLIVES_INC  : RWDLIVES_INC;
			lives_init = (g_incyberspace) ? CYBLIVES_INIT : RWDLIVES_INIT;
			lives_post = (g_incyberspace) ? CYBLIVES_POST : RWDLIVES_POST;
			lives_x = (g_incyberspace) ? CYBLIVES_X : RWDLIVES_X;
			lives_y = (g_incyberspace) ? CYBLIVES_Y : RWDLIVES_Y;
			helth_x = (g_incyberspace) ? CYBHELTH_X : RWDHELTH_X;
			helth_y = (g_incyberspace) ? CYBHELTH_Y : RWDHELTH_Y;
			hw  = ((g_player.hitpoints * helth_width) / INITIAL_LIFE);
			if(hw)
			{
				offset	= helth_width - hw;
				hw	=  hw << 16;
				hw	=  hw | helth_height;
				helthstart=bufstart + (helth_x +(PICWIDTH * helth_y));
				bufferpastehmeter(helthstart, g_helth.data, hw, offset);
			}
			else
				g_player.hitpoints=0;

			livesstart=bufstart + (lives_x +(PICWIDTH * lives_y));
			hw	=  lives_init;
			hw     +=  (g_player.lives == INITIAL_LIVES) ? lives_post : 0;
			hw     +=  (g_player.lives * lives_inc);
			offset	=  lives_width - hw;
			hw	=  hw << 16;
			hw	=  hw | lives_height;
			bufferpastelmeter(livesstart, g_lives.data, hw, offset);
		}
	#ifdef DEBUGGING_ON
			sprintf(message,"%d",g_player.hitpoints);
			printx(150,180,message,bufstart);
			sprintf(message,"%d",g_curframe);
			printx(150,190,message,bufstart);
	#endif

		//bufferpaste(bufstart,g_panel.data,320,200);

		weap_x	= (g_incyberspace) ? CYBWEAP_X : RWDWEAP_X;
		weap_y	= (g_incyberspace) ? CYBWEAP_Y : RWDWEAP_Y;
		strcpy(message,g_weaps[g_selectedweap].weapname);
		g_textcol = g_weapcolors[g_selectedweap];
		printx(weap_x,weap_y,message,bufstart);
		if(g_currentscenenumber > SC_GRWALL)
		{
			strcpy(message,g_tools[g_selectedtool].toolname);
			g_textcol = g_toolcolors[g_selectedtool];
			printx(CYBTOOL_X,CYBTOOL_Y,message,bufstart);
		}
	}

	// --------------------------------------------------------------------
	//   loadConfiguaration()
	//
	// Load up the sound card information set by the SETUP program.  It
	// expects the info to be in c:\firewall\firewall.cfg.
	// --------------------------------------------------------------------

	void loadConfiguaration()
	{
		long	fh;
		char	config[3];
		short	joycfg[6];
		char	cdrom;

		g_inputdevice=INPUT_MOUSE;	/* User input device in use */
		fh=open("firewall.cfg",O_RDONLY,O_BINARY);
		if(fh<0)    // Info not present, ask them to run setup & exit...
		{
			fatalerror("The file firewall.cfg not found.  Please run install.exe");
			return;
		}
		read(fh,&cdrom,1);
		read(fh,&config,3);
		read(fh,&joycfg,12);
		read(fh,&g_soundvol,4);
		close(fh);
		sprintf(g_cdrom, "%c:",cdrom);
		if (config[0]=='y')
		{
			g_gotsound=TRUE;
			initsound();
		//	loadeffects();
			changeVolume(g_soundvol);
		}
		else
		{
			g_gotsound=FALSE;
		}
		if (joycfg[1] > 0) // they have configed a joystick in firewall.cfg...
								// look at joycfg[1] because that holds max x value...
		{
			g_inputdevice = INPUT_JOY;
			g_joydata.centerx=(joycfg[4]/2); // center x point
			g_joydata.centery=(joycfg[5]/2); // center y point
			g_joydata.multx=(joycfg[1]-g_joydata.centerx)/10; // max x - center /10
			g_joydata.multy=(joycfg[3]-g_joydata.centery)/10;  // max y - center /10
			g_joydata.x=g_joydata.centerx;
			g_joydata.y=g_joydata.centery;

			//The New stuff GLR : OCT 25, 95
			xJoyMax = joycfg[1];
			yJoyMax = joycfg[3];
	#ifdef DEBUGGING_ON
			fprintf(dFile,"Joystick Max set at (%d,%d)\n", xJoyMax, yJoyMax);
	#endif
		}
	}

	void closeFirewall()
	{

		// Free buffers (just to be nice)

		if (databuf != NULL)
		{
			free(databuf);
		}
		if (smackBuffer != NULL)
		{
			//free(smackBuffer);
		}
		if (smackBuffer2 != NULL)
		{
			//free(smackBuffer2);
		}
		if (g_gotsound)
		{
			AIL_shutdown();
		}

		FreeBltMemory();       //Free up the Blt memory
		FreeTurnMemory();      //Free up the Menu memory
		FreeMenuMemory();      //Free up the Menu memory
	    FreeEventMemory();	   //Free up the event memory
		FreeSpriteMemory();    //Free up the Sprite memory
	    FreeEventFileMemory(); //Free up the event file memory
	    FreeEventFrameMemory();//Free up the event frame memory
		FreeSceneMusicMemory();//Free up the scene music memory

	#ifdef DEBUGGING_ON
		closeDebug();
	#endif
	}

	#if 0
	void displayPause()
	{
		u8 *bufstart=smackBuffer+g_windowx+352*(g_windowy);
	//  int startX = 160 - (g_pause.width/2);
	//  int startY = 80  - (g_pause.height/2);

		bufferpaste(bufstart,g_pause.data,286,60);

	//  bufferpaste(smackbuffer+(352*50)+20,g_pause.data,286, 60);
	//  bufferpaste(smackBuffer,g_pause.data,g_pause.width,g_pause.height);
		SVGABlit(smackBuffer,g_windowx,g_windowy,320,200,352,0,0);
	}
	#endif

	/*************************************************************************\
	 inittoolsweaps() at portal defenses we're going into cyberspace from the
	 real world, so change the weapons, give them a tool...when the control
	 panels are ready change that..etc.  ADD TO THIS AS NECESSARY!
	 *************************************************************************/
	void inittoolsweaps()
	{
		long x;

		for(x=0; x <(MAX_CYBWEAPONS + MAX_RWDWEAPONS); ++x)
			g_weaps[x].weapaquired = FALSE;

		for(x=0; x < MAX_CYBTOOLS; ++x)
			g_tools[x].weapaquired = FALSE;

		if(g_currentscenenumber < SC_PORTAL)
		{
			g_weaps[WP_Viper].weapaquired	    = TRUE;
			g_weaps[WP_Thunderbolt].weapaquired = TRUE;
			g_selectedweap = WP_Thunderbolt;
		}
		else
		{
	//#ifndef DEBUGGING_ON
			g_weaps[WP_HexRipper1].weapaquired = TRUE;
			g_tools[TL_Matrix].toolaquired = FALSE;
			g_tools[TL_AccessTool].toolaquired = TRUE;
	      sprintf(g_tools[TL_AccessTool].toolname,"%s","ACCESS TOOL");
			g_selectedweap = WP_HexRipper1;
			g_selectedtool = TL_AccessTool;
	//#else
	//		g_weaps[WP_HexRipper2].weapaquired = TRUE;
	//		g_tools[TL_AccessTool].toolaquired = TRUE;
	//		g_tools[TL_Passcode2].toolaquired = TRUE;
	//		g_tools[TL_TraceCutter1].toolaquired = TRUE;
	//		g_tools[TL_LabKey].toolaquired = TRUE;
	//		g_selectedtool = TL_Passcode2;
	//		g_weaps[WP_Cyclone].weapaquired = TRUE;
	//		g_weaps[WP_AiresCom].weapaquired = TRUE;
	////	g_weaps[WP_AIRES].weapaquired = TRUE;
	//		g_weaps[WP_StunHammer].weapaquired = TRUE;
	//		g_weaps[WP_CodeSlammer].weapaquired = TRUE;
	//		g_weaps[WP_HexRipper2].weapaquired = TRUE;
	//		g_weaps[TL_DamageRepair].weapaquired = TRUE;
	//		g_selectedweap = WP_HexRipper2;
	//#endif
		}
		memset(g_playedclue, 0, NUMCLUES);  // initialize g_playedclue array
	}

	void loadblts()
	{
	char message[64];


	 GetBltMemory(-1);

	#ifdef CHUKWUWETA
			sprintf(g_buffer,"c\:\\data\\cybdamg.blt");
	#else
			sprintf(g_buffer,"%s\\data\\cybdamg.blt",g_cdrom);
	#endif
			if(!loadblt(g_buffer,0,256,&g_damg))
			 {
			    sprintf(message,"Couldn't load blt file %s",g_buffer);
				fatalerror(message);
			}

		if(g_currentscenenumber < SC_PORTAL)
		{
	#ifndef  CHUKWUWETA
			sprintf(g_buffer,"%s\\data\\rwdpanel.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_panel))
				fatalerror("Couldn't load blt file rwdpanel.");

			sprintf(g_buffer,"%s\\data\\rwdhelth.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_helth))
				fatalerror("Could not load blt file rwdhelth.");

			sprintf(g_buffer,"%s\\data\\rwdlives.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_lives))
				fatalerror("Couldn't load blt file");
	#else
			sprintf(g_buffer,"c\:\\data\\rwdpanel.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_panel))
				fatalerror("Couldn't load blt file rwdpanel.");

			sprintf(g_buffer,"c\:\\data\\rwdhelth.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_helth))
				fatalerror("Could not load blt file rwdhelth.");

			sprintf(g_buffer,"c\:\\data\\rwdlives.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_lives))
				fatalerror("Couldn't load blt file");
	#endif
		}
		else
		{
	#ifndef  CHUKWUWETA
			sprintf(g_buffer,"%s\\data\\cybpanel.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_panel))
				fatalerror("Couldn't load blt file cybpanel.");

			sprintf(g_buffer,"%s\\data\\cybhelth.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_helth))
				fatalerror("Couldn't load blt file cybhelth.");

			sprintf(g_buffer,"%s\\data\\cyblives.blt",g_cdrom);
			if(!loadblt(g_buffer,192,64,&g_lives))
				fatalerror("Couldn't load blt file cyblives.");

	#else
			sprintf(g_buffer,"c\:\\data\\cybpanel.blt");
			if(!loadblt(g_buffer,192,64,&g_panel))
				fatalerror("Couldn't load blt file cybpanel.blt");

			sprintf(g_buffer,"c\:\\data\\cybhelth.blt");
			if(!loadblt(g_buffer,192,64,&g_helth))
				fatalerror("Couldn't load blt file cybhelth.blt");

			sprintf(g_buffer,"c\:\\data\\cyblives.blt");
			if(!loadblt(g_buffer,192,64,&g_lives))
				fatalerror("Couldn't load blt file cyblives.blt");

	#endif
		}
	}

	#define SPLASHSIZE	(320 * 200)
	void LoadStl(long scenenumber, char *stlname)//, BOOL newscene)
	{
		long sth,readsize;
		char errormsg[32],stillname[32];
		static char *loadbuf = (char *) NULL;
		long wh;
		short width, height;
		char *bufferstart;

	#ifdef CHUKWUWETA
		if(scenenumber > -1)
			sprintf(stillname, "c\:\\data\\%s.stl",g_scenetable[scenenumber]);
		else if(stlname != (char *) NULL)
			sprintf(stillname, "c\:\\data\\%s.stl",stlname);
	#else
		if(scenenumber > -1)
			sprintf(stillname, "%s\\data\\%s.stl", g_cdrom,g_scenetable[scenenumber]);
		else if(stlname != (char *) NULL)
			sprintf(stillname, "%s\\data\\%s.stl", g_cdrom,stlname);
	#endif
		else
		{
			fatalerror("Illegal stl load request\n");
		}

		if((sth=open(stillname,(O_RDONLY | O_BINARY))) <0)
		{
			sprintf(errormsg,"Couldn't open %s\n",stillname);
			fatalerror(errormsg);
		}

		if(!g_stillpalette)
		{
			g_stillpalette = malloc(PALSIZE);
			memset(g_stillpalette,0,PALSIZE);
		}

		if(!loadbuf)
		{
			loadbuf = malloc(SPLASHSIZE);
			memset(loadbuf,0,SPLASHSIZE);
		}

		readsize = read(sth,g_stillpalette,(256 * 3));

		if(!g_still)
		{
			g_still = malloc(SCREENBUFFERSIZE);
			memset(g_still,0,SCREENBUFFERSIZE);
		}

		//readsize = read(sth,g_still,SPLASHSIZE);
		readsize = read(sth,loadbuf,SPLASHSIZE);
		buffer320to352(g_still,loadbuf);
		width  =  34 * FWIDTH;
		height =  FHEIGHT;

	   if(g_stilltextbuffer == (char *) NULL)
		  g_stilltextbuffer = malloc((width * height));

		wh = width;
		wh = wh << 16;
	    wh += height;
		g_wh =wh;
		bufferstart=g_still + 100 + (PICWIDTH * 190);
	    bufferbyteyankfromscr(g_stilltextbuffer, bufferstart, wh);

		close(sth);
	}
